#pragma once
#include <iostream>
#include <memory>
#include "Socket.hpp"
#include "INetAddr.hpp"
#include "Connection.hpp"
#include "Reactor.hpp"
#include "HandlerEvents.hpp"
using namespace socket_ns;

class Listener
{
public:
    Listener(uint16_t port, HandlerEvents& he)
        : _port(port), _listensock(std::make_unique<TcpSocket>()), _he(he)
    {
        _listensock->BuildListenServer(INetAddr("0", port));
    }
    void Accepter(Connection *conn)
    {
        // LOG(INFO, "get a new link from fd : %d\n", conn->GetSockfd());
        while (true)
        {
            INetAddr clientAddr;
            int code = 0;
            int newfd = _listensock->Acceptor(clientAddr, &code);
            if (newfd > 0)
            {
                conn->_R->AddConnection(newfd,
                                        EPOLLIN | EPOLLET,
                                        std::bind(&HandlerEvents::HandlerRecv, &_he, std::placeholders::_1),
                                        std::bind(&HandlerEvents::HandlerSend, &_he, std::placeholders::_1),
                                        std::bind(&HandlerEvents::HandlerExcept, &_he, std::placeholders::_1));
                LOG(INFO, "get a new link from fd : %d\n", newfd);
            }
            else
            {
                if(code == EWOULDBLOCK || code == EAGAIN)
                {
                    LOG(INFO, "accept all fd\n");
                    break;
                }
                else if(code == EINTR)
                {
                    LOG(INFO, "accepting..., signal interrupt\n");
                    continue;
                }
                else
                {
                    LOG(WARNING, "accept error\n");
                    //读取出错
                    conn->_excepter(conn);
                    break;
                }
            }
        }
    }
    int Sockfd()
    {
        return _listensock->Socketfd();
    }
    ~Listener()
    {
        _listensock->Close();
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensock;
    HandlerEvents &_he;
};